package com.leyou.seckill.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.leyou.common.auth.pojo.UserHolder;
import com.leyou.common.constants.LyConstants;
import com.leyou.common.constants.MQConstants;
import com.leyou.common.exception.pojo.ExceptionEnum;
import com.leyou.common.exception.pojo.LyException;
import com.leyou.common.utils.IdWorker;
import com.leyou.common.utils.JsonUtils;
import com.leyou.order.dto.SeckillOrderDTO;
import com.leyou.seckill.interceptor.UserInterceptor;
import com.leyou.seckill.mapper.SeckillMapper;
import com.leyou.seckill.pojo.Seckill;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 秒杀业务
 *
 * @Author jie
 * @Date 2020/11/18
 */
@Service
@Transactional
public class SeckillService {

    @Autowired
    private SeckillMapper seckillMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    private UserInterceptor userInterceptor;

    @Autowired
    private IdWorker idWorker;


    /**
     * 查询所有参与秒杀的商品
     *
     * @return
     */
    public List<Seckill> seckills() {

        BoundHashOperations<String, Object, Object> hashOperations = redisTemplate.boundHashOps(LyConstants.SECKILL_URL_PRE);


        List<Seckill> seckillList = seckillMapper.selectSeckills();

        seckillList.forEach(seckill -> {

            hashOperations.put(seckill.getId().toString(),JsonUtils.toString(seckill));
        });


        List<Seckill> seckills = null;

        if (hashOperations != null) {

            seckills = hashOperations
                    .values()
                    .stream()
                    .map(seckillJson -> JsonUtils.toBean(seckillJson.toString(), Seckill.class))
                    .collect(Collectors.toList());
        }
        return seckills;
    }


    /**
     * 创建秒杀订单
     *
     * @param seckillOrderDTO
     * @return
     */
    public Long buildSeckillOrder(SeckillOrderDTO seckillOrderDTO) {

        //  获取skuId与用户秒杀购买数量
        Long skuId = seckillOrderDTO.getId();
        Integer SeckillNum = seckillOrderDTO.getNum();

        //  获取所有参与秒杀商品
        BoundHashOperations<String, Object, Object> hashOperations = redisTemplate.boundHashOps(LyConstants.SECKILL_URL_PRE);

        //  取出用户要购买的商品
        Object seckillJson = hashOperations.get(skuId.toString());
        Seckill seckill = JsonUtils.toBean(seckillJson.toString(), Seckill.class);

        Date endTime = seckill.getEndTime();

        Date date = new Date(System.currentTimeMillis());

        //  取出商品库存
        Integer stock = seckill.getStock();

        Long seckillOrderId = null;

        //  判断库存是否足够
        if (stock < SeckillNum) {

            //  不够，返回异常
            throw new LyException(ExceptionEnum.STOCK_NOT_ENOUGH_ERROR);
        } else {

            //  够则,Redis中的库存数
            seckill.setStock(stock - SeckillNum);
            hashOperations.put(skuId.toString(), JsonUtils.toString(seckill));

            //  提前创建orderId
            seckillOrderId = idWorker.nextId();

            //  以map携带信息
            Map<String, String> seckillMap = new HashMap<>();

            seckillMap.put("seckillOrderDTO", JsonUtils.toString(seckillOrderDTO));
            seckillMap.put("userInfo", JsonUtils.toString(UserHolder.getUser()));
            seckillMap.put("seckillOrderId", seckillOrderId.toString());

            try {

                //  发送消息
                amqpTemplate.convertAndSend(
                        MQConstants.Exchange.SECKILL_EXCHANGE_NAME,
                        MQConstants.RoutingKey.SECKILL_ORDER_KEY,
                        seckillMap);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

//          返回订单id
        return seckillOrderId;
    }


    /**
     * 根据id查询秒杀商品
     *
     * @param id
     * @return
     */
    public Seckill findSeckillById(Long id) {

        Seckill seckill = new Seckill();
        seckill.setId(id);
        QueryWrapper<Seckill> query = Wrappers.query(seckill);
         seckill = seckillMapper.selectOne(query);
        return seckill;
    }


    /**
     * 根据id修改秒杀商品库存
     *
     * @param cartMap
     * @return
     */
    public void updateSeckill(Map<String,String> cartMap){

        Integer num = Integer.valueOf(cartMap.get("num"));
        Long id = Long.valueOf(cartMap.get("id"));

        Seckill seckill = this.findSeckillById(id);
        seckill.setStock(seckill.getStock()-num);

        seckillMapper.updateById(seckill);
    }
}
